home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / aminet / mus / edit / soundzapv3_0.lha / SoundZAP.c < prev    next >
C/C++ Source or Header  |  1992-06-05  |  27KB  |  1,007 lines

  1. /************/
  2. /**SoundZAP**/
  3. /************/
  4.  
  5. /*
  6.  *  This program was compiled with Matthew Dillon's DICE C compiler, which
  7.  *  automatically opens and closes the Amiga libraries as they are needed.
  8.  *  If your compiler does not do this you will have to Add the appropriate
  9.  *  code (or get DICE!!).
  10.  */
  11.  
  12.  
  13. #include "SoundZAP.h"
  14.  
  15. void main(int argc, char *argv[])
  16. {
  17.     char comline[33];
  18.     struct options *Opt;
  19.  
  20.  
  21.     if (argc<2) GiveUsage();
  22.  
  23.     printf(SZVER);
  24.     printf(" -- 3 June 1992 -- (c) Michael Cramer\n\n");
  25.  
  26.     if ((Opt=(struct options *)malloc(sizeof(struct options)))==NULL)
  27.         CleanUp(Opt,5);
  28.  
  29.     Opt->BuffSize    = DEFAULT_SIZE;
  30.     Opt->Size        = 0;
  31.     Opt->InSign      = TRUE;
  32.     Opt->OutSign     = TRUE;
  33.     Opt->KillChunk   = FALSE;
  34.     Opt->FibDeltIn   = FALSE;
  35.     Opt->MuLawIn     = FALSE;
  36.     Opt->MuLawOut    = FALSE;
  37.     Opt->SampRate    = 0;
  38.     Opt->NewRate     = 0;
  39.     Opt->Data        = NULL;
  40.     Opt->Amp         = 3;
  41.     Opt->Bits        = 8;
  42.     Opt->InType      = UNKNOWN;
  43.     Opt->OutType     = IFF;
  44.     Opt->inname[0]   = '\0';
  45.     Opt->outname[0]  = '\0';
  46.     Opt->FileName[0] = '\0';
  47.     Opt->Auth        = NULL;
  48.     Opt->Copy        = NULL;
  49.  
  50.     while (--argc > 0)
  51.     {
  52.         strcpy(comline,argv[argc]);
  53.         if (comline[0]=='-')
  54.             ProcessOpt(Opt,comline);
  55.         else
  56.         {
  57.            strcpy(Opt->outname,Opt->inname);
  58.            strcpy(Opt->inname,comline);
  59.         }
  60.     }
  61.  
  62.     if (strlen(Opt->inname)==0)
  63.         GiveUsage();
  64.  
  65.     if (strlen(Opt->outname)==0)
  66.     {
  67.         int l;
  68.  
  69.         strcpy(Opt->outname,Opt->inname);
  70.         l=strlen(Opt->outname);
  71.         if(Opt->outname[l-4]=='.')
  72.             Opt->outname[l-4]='\0';
  73.         if(Opt->outname[l-3]=='.')
  74.             Opt->outname[l-3]='\0';
  75.         AFlag=TRUE;
  76.     }
  77.     else
  78.         AFlag=FALSE;
  79.     strcpy(Opt->FileName,Opt->outname);
  80.     AnalyzeData(Opt);
  81.     CleanUp(Opt,0);
  82. }
  83.  
  84.  
  85. void GiveUsage()
  86. {
  87.     printf(SZVER);
  88.     printf("\nUsage:  SoundZAP [<options>] SOURCE [DESTINATION]\n");
  89.     printf("    (actually, the options can appear anywhere)\n\n");
  90.     printf("    options     -a<n>   Amplify by n/3 times\n");
  91.     printf("\t\t-b<n>   Use a buffer size of n kilobytes\n");
  92.     printf("\t\t-c<n>   Physically resample data to n\n");
  93.     printf("\t\t-f      Assume input data is RAW\n");
  94.     printf("\t\t-l      Output u-lawed data\n");
  95.     printf("\t\t-n      Don't create extra chunks in IFF output\n");
  96.     printf("\t\t-r<n>   Change sample rate to n\n");
  97.     printf("\t\t-s      Output a Sun .au file\n");
  98.     printf("\t\t-u      Output UNSIGNED data\n");
  99.     printf("\t\t-w      Output RAW data\n");
  100.     printf("\nSee documentation for more info.\n");
  101.     printf("mrc113@psuvm.psu.edu\n");
  102.     exit(0);
  103. }
  104.  
  105. void ProcessOpt(struct options *Opt, char com[])
  106. {
  107.     int len;
  108.  
  109.     switch (com[1])
  110.     {
  111.         case 'a' : len=strlen(com)-2;
  112.                    if (len==0)
  113.                         Opt->Amp=0;
  114.                    Opt->Amp=(UBYTE)atoi(com+2);
  115.                    break;
  116.  
  117.         case 'b' :  len=strlen(com)-2;
  118.                     if (len==0)
  119.                         Opt->BuffSize=0;
  120.                     Opt->BuffSize=(ULONG)atoi(com+2)*1024;
  121.                     break;
  122.  
  123.         case 'c' :  Opt->NewRate = GetRateFromString(Opt, com+2);
  124.                     break;
  125.  
  126.         case 'f' :  Opt->InType=RAW;
  127.                     break;
  128.  
  129.         case 's' :  Opt->OutType=AU;
  130.                     Opt->MuLawOut=TRUE;
  131.                     Opt->NewRate=8000;
  132.                     break;
  133.  
  134.         case 'w' :  Opt->OutType=RAW;
  135.                     break;
  136.  
  137.         case 'l' :  Opt->MuLawOut=TRUE;
  138.                     break;
  139.  
  140.         case 'n' :  Opt->KillChunk=TRUE;
  141.                     break;
  142.  
  143.         case 'r' :  Opt->SampRate = GetRateFromString(Opt, com+2);
  144.                     break;
  145.  
  146.         case 'u' :  Opt->OutSign=FALSE;
  147.                     break;
  148.  
  149.         default  :  CleanUp(Opt,4);
  150.     }
  151. }
  152.  
  153. UWORD GetRateFromString(struct options *Opt, char *c)
  154. {
  155.         int len;
  156.         UWORD n;
  157.  
  158.         len=strlen(c);
  159.         if (len==0)
  160.             CleanUp(Opt,3);
  161.         if (len==1)
  162.         {
  163.             switch (c[0])
  164.            {
  165.                case '5' :  n=5696;
  166.                            break;
  167.  
  168.                case '7' :  n=7596;
  169.                            break;
  170.  
  171.                case '8' :  n=8000;
  172.                            break;
  173.  
  174.                case '2' :  n=22790;
  175.                            break;
  176.  
  177.                default  :  n=11395;
  178.            }
  179.        }
  180.        else
  181.        {
  182.             n=(UWORD)atoi(c);
  183.             if (!n) n=11395;
  184.        }
  185.        return n;
  186. }
  187.  
  188. void CleanUp(struct options *Opt, int Error)
  189. {
  190.     if (Opt->Data) free(Opt->Data);
  191.     if (Opt->Auth) free(Opt->Auth);
  192.     if (Opt->Copy) free(Opt->Copy);
  193.     if (Opt) free(Opt);
  194.     if (in)   Close(in);
  195.     if (out)  Close(out);
  196.     if (Error==0) exit(0);
  197.     else
  198.     {
  199.         printf("%s",ErrorMessages[Error]);
  200.         exit(20);
  201.     }
  202. }
  203.  
  204. void AnalyzeData(struct options *Opt)
  205. {
  206.     ULONG MagicWord;
  207.     char IsMac[8];
  208.  
  209.     if ((in=(struct FileHandle *)Open(Opt->inname,MODE_OLDFILE))==NULL)
  210.         CleanUp(Opt,6);
  211.  
  212.     if(Opt->BuffSize==0)
  213.     {
  214.         Seek(in,0,OFFSET_END);
  215.         Opt->BuffSize = (Seek(in,0,OFFSET_BEGINNING) + 1) & ~1;
  216.     }
  217.  
  218.     if ((Opt->Data=(BYTE *)malloc(Opt->BuffSize))==NULL)
  219.         CleanUp(Opt,5);
  220.  
  221.     Read(in,&MagicWord,4);
  222.     if (Opt->InType==UNKNOWN)
  223.     {
  224.         if (MagicWord==0x2e736e64)                /* '.snd' */
  225.             ConvertAU(Opt);
  226.         else if (MagicWord==0x464f524d)           /* 'FORM' */
  227.             ConvertIFF(Opt);
  228.         else if (MagicWord==0x43726561)           /* 'Crea' */
  229.             ConvertVOC(Opt);
  230.         else if (MagicWord==0x52494646)           /* 'RIFF' */
  231.             ConvertWAV(Opt);
  232.         else
  233.         {
  234.         Seek(in,65,OFFSET_BEGINNING);
  235.         Read(in,IsMac,8);
  236.         if (!strcmp(IsMac,"FSSDSFX!"))
  237.             ConvertMAC(Opt);
  238.         else
  239.             GuidoCheck(Opt);
  240.         }
  241.     }
  242.     ConvertRaw(Opt);
  243. }
  244.  
  245. /*  This routine is a modified version of Guido van Rossum's (guido@cwi.nl)
  246.  *  'whatsound' routine. It guesses the sound file type (signed/unsigned/u-law)
  247.  *  by checking how the values in the file are distributed. Thanks Guido!!
  248.  */
  249.  
  250. void GuidoCheck(struct options *Opt)
  251. {
  252.     LONG a,n;
  253.     ULONG bin[4];
  254.     int x;
  255.  
  256.  
  257.     Opt->InType=RAW;
  258.     for (a=0; a<4; a++)
  259.         bin[a]=0;
  260.     do
  261.     {
  262.         n=Read(in,Opt->Data,Opt->BuffSize);
  263.         for(a=0; a<n; a++)
  264.             bin[(UBYTE)Opt->Data[a]/64]++;
  265.     }
  266.     while (n==Opt->BuffSize);
  267.     if((bin[2]==0) && (bin[3]==0))
  268.         CleanUp(Opt,7);
  269.  
  270.     x=((bin[0]+bin[3])*100)/(bin[1]+bin[2]);
  271.  
  272.     if(x>=300)
  273.         Opt->InSign=TRUE;
  274.     else if ( x <= 33)
  275.         Opt->InSign=FALSE;
  276.     else if ( (x >= 50) && (x <= 200))
  277.     {
  278.         Opt->MuLawIn=TRUE;
  279.         if(Opt->SampRate==0) Opt->SampRate=8000;
  280.     }
  281.  
  282.     if(!Opt->SampRate)
  283.         Opt->SampRate=11395;
  284.     Seek(in,0,OFFSET_END);
  285.     Opt->Size=Seek(in,0,OFFSET_BEGINNING);
  286. }
  287.  
  288.  
  289. void ConvertRaw(struct options *Opt)
  290. {
  291.     LONG b_read,i,scale,b_written,total,t,BuffSize;
  292.     int max;
  293.     signed char logs[256];
  294.     unsigned char ulawbytes[256];
  295.     BPTR op=Output();
  296.     BYTE max2=0, *Data, x;
  297.  
  298.  
  299.     if(AFlag)
  300.         switch (Opt->OutType)
  301.         {
  302.             case IFF :  strcat(Opt->outname,".iff");
  303.                         break;
  304.  
  305.             case RAW :  strcat(Opt->outname,".raw");
  306.                         break;
  307.  
  308.             case AU  :  strcat(Opt->outname,".au");
  309.                         break;
  310.  
  311.             default  :  strcat(Opt->outname,".out");
  312.         }
  313.  
  314.     if((out=(struct FileHandle *)Open(Opt->outname,MODE_NEWFILE))==NULL)
  315.         CleanUp(Opt,8);
  316.  
  317.     if (Opt->MuLawIn && (!Opt->MuLawOut))
  318.     {
  319.         Opt->Amp=3;
  320.         max=getscale(Opt);
  321.         maketable(logs,max);
  322.         if (Opt->InType==AU)
  323.             Seek(in,32,OFFSET_BEGINNING);
  324.         else
  325.             Seek(in,0,OFFSET_BEGINNING);
  326.     }
  327.  
  328.     if (Opt->MuLawOut && (!Opt->MuLawIn))
  329.         maketableII(ulawbytes);
  330.  
  331.     scale=Opt->Bits/8;
  332.  
  333.     if (!Opt->Amp)
  334.     {
  335.         LONG tmppos;
  336.         BYTE a;
  337.  
  338.         total=0;
  339.         tmppos=Seek(in,0,OFFSET_CURRENT);
  340.         do
  341.         {
  342.             b_read=Read(in,Opt->Data,Opt->BuffSize)/scale;
  343.             for(i=0; i<b_read; i++)
  344.                 max2=MAX(max2,Opt->Data[i*scale]);
  345.             total+=b_read;
  346.         }
  347.         while (total < Opt->Size);
  348.         Seek(in,tmppos,OFFSET_BEGINNING);
  349.     }
  350.  
  351.     if(Opt->NewRate)
  352.         Opt->Size = Opt->Size * Opt->NewRate / Opt->SampRate;
  353.  
  354.     PrintIOInfo(Opt);
  355.  
  356.     switch (Opt->OutType)
  357.     {
  358.         case IFF :  WriteIFFStuff(Opt); break;
  359.         case AU  :  WriteAUStuff(Opt); break;
  360.     }
  361.  
  362.     if ( Opt->FibDeltIn )
  363.     {
  364.         BuffSize = Opt->BuffSize >> 1;
  365.         Data = Opt->Data + BuffSize;
  366.         Read (in, &x, 1);
  367.         Read (in, &x, 1);
  368.     }
  369.     else
  370.     {
  371.         BuffSize = Opt->BuffSize;
  372.         Data = Opt->Data;
  373.     }
  374.  
  375.     total=0;
  376.     do
  377.     {
  378.         b_read=Read(in, Data, BuffSize)/scale;
  379.  
  380.         if (Opt->FibDeltIn)
  381.         {
  382.             x = D1Unpack(Data,b_read,Opt->Data,x);
  383.             b_read <<= 1;
  384.         }
  385.  
  386.         if(Opt->MuLawIn && (!Opt->MuLawOut))
  387.             for (i=0; i<b_read; i++)
  388.                 Opt->Data[i]=logs[(UBYTE)Opt->Data[i]];
  389.         else
  390.         {
  391.             if(scale!=1)
  392.                 for (i=0; i<b_read; i++)
  393.                     Opt->Data[i]=Opt->Data[i*scale];
  394.  
  395.             if(Opt->Amp && (Opt->Amp!=3))
  396.                 for (i=0; i<b_read; i++)
  397.                     Opt->Data[i]=Opt->Amp*Opt->Data[i]/3;
  398.             else if((Opt->Amp==0) && (max2 != 127))
  399.                 for (i=0; i<b_read; i++)
  400.                     Opt->Data[i]=Opt->Data[i]*127/max2;
  401.         }
  402.  
  403.         if(Opt->NewRate)
  404.         {
  405.             for(t=0; t<(b_read * Opt->NewRate / Opt->SampRate); t++)
  406.                 Opt->Data[t]=Opt->Data[t * Opt->SampRate / Opt->NewRate];
  407.             b_read = b_read * Opt->NewRate / Opt->SampRate;
  408.         }
  409.  
  410.         if(Opt->InSign != Opt->OutSign)
  411.             for (i=0; i<b_read; i++)
  412.                 Opt->Data[i] ^= 0x80;
  413.  
  414.         if(Opt->MuLawOut && (!Opt->MuLawIn))
  415.             for (i=0; i<b_read; i++)
  416.                 Opt->Data[i] = ulawbytes[(unsigned char)Opt->Data[i]];
  417.  
  418.         total+=b_read;
  419.  
  420.         b_written=Write(out,Opt->Data,b_read);
  421.         FileLen+=b_written;
  422.         if(b_written!=b_read) CleanUp(Opt,10);
  423.     }
  424.     while((total < Opt->Size) && (b_read > 0));
  425.  
  426.     if((Opt->OutType == IFF) && (total & 1))
  427.         FileLen+=Write(out,'\0',1);
  428.  
  429.     if(Opt->OutType == IFF)
  430.         FixSize(Opt, total);
  431.  
  432.     CleanUp(Opt,0);
  433. }
  434.  
  435. void FixSize(struct options *Opt, ULONG total)
  436. {
  437.     FileLen-=8;
  438.     Seek(out,4,OFFSET_BEGINNING);
  439.     Write(out,&FileLen,4);
  440.     Seek(out,BodySpot+4,OFFSET_BEGINNING);
  441.     Write(out,&total,4);
  442.     Seek(out,20,OFFSET_BEGINNING);
  443.     Write(out,&total,4);
  444. }
  445.  
  446.  
  447. void WriteIFFStuff(struct options *Opt)
  448. {
  449.     ULONG i;
  450.     ChunkHeader Head;
  451.     time_t t;
  452.     struct tm *tp;
  453.     char datetime[50];
  454.  
  455.     Voice8Header V8H = {0,0,32,8363,1,0,Unity};
  456.  
  457.     Head.ckID = FORM;
  458.     Head.ckSize = 0;
  459.  
  460.     FileLen+=Write(out,&Head,8);
  461.  
  462.     i=ID_8SVX;
  463.     FileLen+=Write(out,&i,4);
  464.  
  465.     Head.ckID = ID_VHDR;
  466.     Head.ckSize = 20;
  467.     FileLen+=Write(out,&Head,8);
  468.  
  469.     V8H.oneShotHiSamples = 0;
  470.     V8H.samplesPerSec = Opt->NewRate ? Opt->NewRate : Opt->SampRate;
  471.     FileLen+=Write(out,&V8H,20);
  472.  
  473.     if (!Opt->KillChunk)
  474.     {
  475.         i=strlen(Opt->FileName);
  476.         printf("NAME: %s\n",Opt->FileName);
  477.         Head.ckID = ID_NAME;
  478.         Head.ckSize = i;
  479.         FileLen+=Write(out,&Head,8);
  480.         FileLen+=Write(out,Opt->FileName,i);
  481.         FileLen+=Write(out,'\0',i & 1);
  482.  
  483.         if(!Opt->Auth)
  484.         {
  485.             if(!(Opt->Auth=(char *)malloc(strlen(SZVER)+25)))
  486.                 CleanUp(Opt,5);
  487.             strcpy(Opt->Auth,SZVER);
  488.             strcat(Opt->Auth," by mrc113@psuvm.psu.edu");
  489.         }
  490.         i=strlen(Opt->Auth);
  491.         printf("AUTH: %s\n",Opt->Auth);
  492.         Head.ckID  = ID_AUTH;
  493.         Head.ckSize = i;
  494.         FileLen+=Write(out,&Head,8);
  495.         FileLen+=Write(out,Opt->Auth,i);
  496.         FileLen+=Write(out,'\0',i & 1);
  497.  
  498.  
  499.         t=time(NULL);
  500.         tp=localtime(&t);
  501.         i=strftime(datetime,49,"Converted: %d %b %Y %X by SoundZAP",tp);
  502.         printf("ANNO: %s\n",datetime);
  503.         Head.ckID = ID_ANNO;
  504.         Head.ckSize = i;
  505.         FileLen+=Write(out,&Head,8);
  506.         FileLen+=Write(out,datetime,i);
  507.         FileLen+=Write(out,'\0',i & 1);
  508.  
  509.         if(strlen(Opt->Copy))
  510.         {
  511.             i=strlen(Opt->Copy);
  512.             printf("Copyright: %s\n",Opt->Copy);
  513.             Head.ckID = ID_Copyright;
  514.             Head.ckSize = i;
  515.             FileLen+=Write(out,&Head,8);
  516.             FileLen+=Write(out,Opt->Copy,i);
  517.             FileLen+=Write(out,'\0',i & 1);
  518.         }
  519.     }
  520.  
  521.     BodySpot=Seek(out,0,OFFSET_CURRENT);
  522.  
  523.     Head.ckID = ID_BODY;
  524.     Head.ckSize = 0L;
  525.     FileLen+=Write(out,&Head,8);
  526. }
  527.  
  528. void WriteAUStuff(struct options *Opt)
  529. {
  530.     AUHeader AUH;
  531.  
  532.     AUH.magic=0x2e736e64;   /* '.snd' */
  533.     AUH.hrd_size=24;
  534.     AUH.channels=1;
  535.     AUH.sample_rate=8000;
  536.     Opt->NewRate=8000;
  537.     AUH.encoding=1;
  538.     AUH.data_size=0;
  539.     FileLen+=Write(out,&AUH,24);
  540. }
  541.  
  542. void PrintIOInfo(struct options *Opt)
  543. {
  544.     printf("\n%s -> %s\n\n",Opt->inname,Opt->outname);
  545.     printf("Convert from ");
  546.     switch (Opt->InType)
  547.     {
  548.         case IFF  : printf("IFF 8SVX to "); break;
  549.         case AU   : printf(".au to "); break;
  550.         case RAW  : printf("Raw data to "); break;
  551.         case AIFF : printf("AIFF to "); break;
  552.         case VOC  : printf(".voc to "); break;
  553.         case WAV  : printf(".wav to "); break;
  554.         case MAC  : printf("Macintosh to "); break;
  555.         default   : printf(" <UNKNOWN> to ");
  556.     }
  557.     switch (Opt->OutType)
  558.     {
  559.         case IFF  : printf("IFF 8SVX\n"); break;
  560.         case AU   : printf(".au\n"); break;
  561.         case RAW  : printf("Raw data\n"); break;
  562. /*
  563.         case AIFF : printf("AIFF\n"); break;
  564.         case VOC  : printf(".voc\n"); break;
  565.         case WAV  : printf(".wav\n"); break;
  566.         case MAC  : printf("Macintosh\n"); break;
  567.  */
  568.         default   : printf(" <UNKNOWN>\n");
  569.     }
  570.     printf("\nInput data is ");
  571.     if(Opt->MuLawIn)
  572.         printf("u-lawed, ");
  573.     else
  574.         printf(Opt->InSign ? "signed, " : "unsigned, ");
  575.     if (Opt->FibDeltIn) printf("Fibonacci Delta encoded, ");
  576.     printf("and the output data is ");
  577.     if(Opt->MuLawOut)
  578.         printf("u-lawed\n");
  579.     else
  580.         printf(Opt->OutSign ? "signed\n" : "unsigned\n");
  581.  
  582.     printf("Input data is %d bits per sample, %d samples per second\n",Opt->Bits,Opt->SampRate);
  583.  
  584.     if (Opt->NewRate)
  585.         printf("Output data is re-sampled to %d samples per second\n",Opt->NewRate);
  586.  
  587.     printf("\nBuffer size: %d bytes\n",Opt->BuffSize);
  588.  
  589.     if(!Opt->Amp)
  590.         printf("\nOutput data amplified to maximum\n");
  591.     else if (Opt->Amp != 3)
  592.         printf("\nOutput data amplified %d thirds times\n",Opt->Amp);
  593.  
  594.     if(Opt->OutType == IFF)
  595.         if(Opt->KillChunk) printf("\nSuppress extra chunk creation\n");
  596.         else printf("\nChunks to be written to IFF file:\n");
  597. }
  598.  
  599. void ConvertVOC(struct options *Opt)
  600. {
  601.     UBYTE c[2];
  602.  
  603.     if(!Opt->SampRate)
  604.     {
  605.         Seek(in,30,OFFSET_BEGINNING);
  606.         Read(in,c,2);
  607.         if(c[1]!=0)
  608.             CleanUp(Opt,9);
  609.         Opt->SampRate=1000000/(256-c[0]);
  610.     }
  611.     Opt->InSign=FALSE;
  612.     Seek(in,0,OFFSET_END);
  613.     Opt->Size=Seek(in,0,OFFSET_BEGINNING)-32;
  614.     Seek(in,32,OFFSET_BEGINNING);
  615.     Opt->InType=VOC;
  616. }
  617.  
  618. void ConvertWAV(struct options *Opt)
  619. {
  620.     ChunkHeader Head;
  621.     ULONG FileSize;
  622.     ULONG FileType;
  623.     LONG b_read;
  624.     WaveFmtChunk fmt;
  625.  
  626.     Seek(in,0,OFFSET_BEGINNING);
  627.     Read(in,&Head,8);
  628.     if(Head.ckID != RIFF)
  629.         CleanUp(Opt,12);
  630.     FileSize = SCREWINTEL(Head.ckSize);
  631.  
  632.     b_read=Read(in,&FileType,4);
  633.     if(FileType != WAVE)
  634.         CleanUp(Opt,12);
  635.  
  636.     while((Head.ckID != DATA) && b_read)
  637.     {
  638.         b_read = Read(in,&Head,8);
  639.         if (b_read)
  640.         {
  641.             Head.ckSize = SCREWINTEL(Head.ckSize);
  642.             if (Head.ckID == FMT)
  643.             {
  644.                 Read(in,&fmt,sizeof(WaveFmtChunk));
  645.                 if(fmt.wChannels != 0x0100)
  646.                     CleanUp(Opt,15);
  647.                 if(fmt.wFormatTag != 0x0100)
  648.                     CleanUp(Opt,9);
  649.                 Opt->SampRate = SCREWINTEL(fmt.dwSamplesPerSec);
  650.                 Seek(in,Head.ckSize - sizeof(WaveFmtChunk),OFFSET_CURRENT);
  651.             }
  652.             else if (Head.ckID == DATA)
  653.                 Opt->Size = SCREWINTEL(Head.ckSize);
  654.             else
  655.                 Seek(in,(SCREWINTEL(Head.ckSize) + 1) & ~1 ,OFFSET_CURRENT);
  656.         }
  657.     }
  658.     Opt->InSign=FALSE;
  659.     Opt->InType=WAV;
  660. }
  661.  
  662. void ConvertMAC(struct options *Opt)
  663. {
  664.     USHORT len;
  665.     char *name;
  666.  
  667.     Opt->InSign=FALSE;
  668.     Seek(in,0,OFFSET_END);
  669.     Opt->Size=Seek(in,0,OFFSET_BEGINNING)-668;
  670.     Read(in,&len,2);
  671.     name=(char *)malloc(len);
  672.     Read(in,name,len);
  673.     name[len]='\0';
  674.     strcpy(Opt->FileName,name);
  675.     Seek(in,128,OFFSET_BEGINNING);
  676.     if (!Opt->SampRate)
  677.         Opt->SampRate=11395;
  678.     free(name);
  679.     Opt->InType=MAC;
  680. }
  681.  
  682. /* Thanks to Sean Connolly for sending me info on the .au sound format.*/
  683.  
  684. void ConvertAU(struct options *Opt)
  685. {
  686.     AUHeader AUHdr;
  687.  
  688.     Seek(in,0,OFFSET_END);
  689.     Opt->Size=Seek(in,0,OFFSET_BEGINNING)-32;
  690.     Read(in,&AUHdr,28);
  691.     switch (AUHdr.encoding)
  692.     {
  693.         case 1   :  Opt->MuLawIn=TRUE;
  694.                     break;
  695.  
  696.         case 2   :  Opt->Bits=8;
  697.                     break;
  698.  
  699.         case 3   :  Opt->Bits=16;
  700.                     Opt->Size/=2;
  701.                     break;
  702.  
  703.         case 4   :  Opt->Bits=24;
  704.                     Opt->Size/=3;
  705.                     break;
  706.  
  707.         case 5   :  Opt->Bits=32;
  708.                     Opt->Size/=4;
  709.                     break;
  710.  
  711.         default  :  CleanUp(Opt,9);
  712.                     break;
  713.     }
  714.  
  715.     if (!Opt->SampRate)
  716.         Opt->SampRate=AUHdr.sample_rate;
  717.  
  718.     Opt->InType=AU;
  719. }
  720.  
  721. void ConvertIFF(struct options *Opt)
  722. {
  723.     struct ChunkInfo List, *This, *Next;
  724.     Voice8Header V8H;
  725.     CommonChunk CC;
  726.     char *data;
  727.     int Help=0;
  728.     BOOL Flag=TRUE;
  729.  
  730.     List=GetChunks(Get,9,in);
  731.  
  732.     if (List.Next == NULL)
  733.         Help=11;
  734.     else
  735.     {
  736.         switch(List.Name)
  737.         {
  738.             case ID_8SVX    : Opt->InType=IFF; break;
  739.             case ID_AIFF    : Opt->InType=AIFF; break;
  740.             default         : Help=11;
  741.         }
  742.     }
  743.  
  744.     Next=List.Next;
  745.     while(Next)
  746.     {
  747.         This=Next;
  748.         Seek(in,This->Pos,OFFSET_BEGINNING);
  749.         switch(This->Name)
  750.         {
  751.             case ID_COMM : Read(in,&CC,18);
  752.                            Opt->Size=CC.numSampleFrames;
  753.                            Opt->Bits=(CC.sampleSize+7)/8;
  754.                            Opt->Bits*=8;
  755.                            break;
  756.  
  757.             case ID_SSND : Seek(in,8,OFFSET_CURRENT); /*Don't use it for anything so just get to the right place */
  758.                            break;
  759.  
  760.             case ID_VHDR : Read(in,&V8H,20);
  761.                            if (!Opt->SampRate)
  762.                                Opt->SampRate=V8H.samplesPerSec;
  763.                            if(V8H.sCompression) Opt->FibDeltIn=TRUE;
  764.                            break;
  765.  
  766.             case ID_BODY : Opt->Size=This->Size;
  767.                            break;
  768.  
  769.         /* AUTH and Copyright must be preserved! */
  770.  
  771.             case ID_AUTH : if(!(Opt->Auth=(char *)malloc(This->Size)))
  772.                                CleanUp(Opt,5);
  773.                            Read(in,Opt->Auth,This->Size);
  774.                            Opt->Auth[This->Size]='\0';
  775.                            if (!strncmp(Opt->Auth,"SoundZAP",8))
  776.                            {
  777.                                 free(Opt->Auth);
  778.                                 Opt->Auth=NULL;
  779.                            }
  780.                            break;
  781.  
  782.             case ID_Copyright : if(!(Opt->Copy=(char *)malloc(This->Size)))
  783.                                     CleanUp(Opt,5);
  784.                                 Read(in,Opt->Copy,This->Size);
  785.                                 Opt->Copy[This->Size]='\0';
  786.                                 break;
  787.  
  788.             case ID_NAME : if(!(data=(char *)malloc(This->Size)))
  789.                                CleanUp(Opt,5);
  790.                            Read(in,data,This->Size);
  791.                            data[This->Size]='\0';
  792.                            if (Flag) printf("Chunks found but not preserved:\n");
  793.                            printf("NAME: %s\n",data);
  794.                            free(data);
  795.                            Flag=FALSE;
  796.                            break;
  797.  
  798.             case ID_ANNO : if(!(data=(char *)malloc(This->Size)))
  799.                                CleanUp(Opt,5);
  800.                            Read(in,data,This->Size);
  801.                            data[This->Size]='\0';
  802.                            if (Flag) printf("Chunks found but not preserved:\n");
  803.                            Flag=FALSE;
  804.                            printf("ANNO: %s\n",data);
  805.                            free(data);
  806.                            break;
  807.  
  808.             case ID_TEXT : if(!(data=(char *)malloc(This->Size)))
  809.                                CleanUp(Opt,5);
  810.                            Read(in,data,This->Size);
  811.                            data[This->Size]='\0';
  812.                            if (Flag) printf("Chunks found but not preserved:\n");
  813.                            Flag=FALSE;
  814.                            printf("TEXT: %s\n",data);
  815.                            free(data);
  816.                            break;
  817.         }
  818.         Next=This->Next;
  819.         free(This);
  820.     }
  821.     if (Help)
  822.         CleanUp(Opt,Help);
  823. }
  824.  
  825.  
  826. /*--------------------------------------------------------------------------*
  827.  * The following routine was extracted from posting by Brian Foley.         *
  828.  * Brian Foley          email: bfoley@greatlakes.Central.Sun.COM            *
  829.  * Systems Engineer     smail:  1000 Town Center                            *
  830.  * Sun Microsystems             Suite 1700                                  *
  831.  * GreatLakes Region            Southfield, MI 48075   (313) 352-7070       *
  832.  *--------------------------------------------------------------------------*/
  833.  
  834. int ulaw2linear(unsigned char ulawbyte)
  835. {
  836.         static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
  837.                int sign, exponent, mantissa, sample;
  838.  
  839.         ulawbyte    = ~ulawbyte;
  840.         sign        =  ulawbyte & 0x80;
  841.         exponent    = (ulawbyte >> 4) & 0x07;
  842.         mantissa    =  ulawbyte & 0x0F;
  843.         sample      = (exp_lut[exponent] + (mantissa << (exponent + 3)));
  844.         if ( sign ) sample = -sample;
  845.         return sample;
  846. }
  847.  
  848. int getscale(struct options *Opt)
  849. {
  850.         int count, max = 0, i;
  851.  
  852.         do
  853.         {
  854.             count    = Read(in, Opt->Data, Opt->BuffSize);
  855.             for ( i = 0; i < count; i++ )
  856.                 max     = MAX(abs(ulaw2linear(Opt->Data[i])), max);
  857.         }
  858.         while ( count == Opt->BuffSize );
  859.  
  860.         return max;
  861. }
  862.  
  863. void maketable(signed char *logs, int max)
  864. {
  865.         int i, c, d;
  866.  
  867.         for ( i = 0; i < 256; i++ )
  868.         {
  869.                 c = ( ulaw2linear(i) * ulaw2linear(0) ) / max;
  870.                 d = abs(c) & 0xFF;
  871.                 if ( d > 0x7F )
  872.                     if ( c > 0 )
  873.                         logs[i] = (signed char) ( c / 256 + 1 );
  874.                     else
  875.                         logs[i] = (signed char) ( c / 256 - 1 );
  876.                 else
  877.                     logs[i] = (signed char) ( c / 256 );
  878.         }
  879. }
  880.  
  881. void maketableII(unsigned char *ubytes)
  882. {
  883.     signed int i;
  884.  
  885.     for(i=0; i<256; i++)
  886.         ubytes[i]=st_linear_to_ulaw((signed char)i);
  887. }
  888.  
  889. /*
  890. ** This routine converts from linear to ulaw.
  891. **
  892. ** Craig Reese: IDA/Supercomputing Research Center
  893. ** Joe Campbell: Department of Defense
  894. ** 29 September 1989
  895. **
  896. ** References:
  897. ** 1) CCITT Recommendation G.711  (very difficult to follow)
  898. ** 2) "A New Digital Technique for Implementation of Any
  899. **     Continuous PCM Companding Law," Villeret, Michel,
  900. **     et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
  901. **     1973, pg. 11.12-11.17
  902. ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
  903. **     for Analog-to_Digital Conversion Techniques,"
  904. **     17 February 1987
  905. **
  906. ** Input: Signed 16 bit linear sample
  907. ** Output: 8 bit ulaw sample
  908. */
  909.  
  910. #define BIAS 0x84   /* define the add-in bias for 16 bit samples */
  911. #define CLIP 32635
  912.  
  913. unsigned char st_linear_to_ulaw( signed char oldsample )
  914. {
  915.     static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
  916.                                4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
  917.                                5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  918.                                5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
  919.                                6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  920.                                6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  921.                                6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  922.                                6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
  923.                                7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  924.                                7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  925.                                7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  926.                                7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  927.                                7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  928.                                7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  929.                                7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
  930.                                7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
  931.     int sign, exponent, mantissa, sample;
  932.     unsigned char ulawbyte;
  933.  
  934.     sample=oldsample << 8;
  935.     /* Get the sample into sign-magnitude. */
  936.     sign = (sample >> 8) & 0x80;               /* set aside the sign */
  937.     if ( sign != 0 ) sample = -sample;         /* get magnitude */
  938.     if ( sample > CLIP ) sample = CLIP;                /* clip the magnitude */
  939.  
  940.     /* Convert from 16 bit linear to ulaw. */
  941.     sample = sample + BIAS;
  942.     exponent = exp_lut[( sample >> 7 ) & 0xFF];
  943.     mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
  944.     ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
  945. /*
  946.     if ( ulawbyte == 0 ) ulawbyte = 0x02;
  947. */
  948.     return ulawbyte;
  949. }
  950.  
  951. struct ChunkInfo GetChunks(ULONG *Names, int n, struct FileHandle *in)
  952. {
  953.     LONG Size, pos=0,b_read;
  954.     ChunkHeader Head;
  955.     struct ChunkInfo List, *ThisNode;
  956.     ID Type;
  957.     int i;
  958.  
  959.     Seek(in,0,OFFSET_END);
  960.     Size=Seek(in,0,OFFSET_BEGINNING);
  961.     if(Size < 50)
  962.     {
  963.         List.Size=ERROR_IN_FORM;
  964.         List.Next=NULL;
  965.         return List;
  966.     }
  967.  
  968.     pos+=Read(in,&Head,8);
  969.     if (Head.ckID != FORM)
  970.     {
  971.         List.Size=ERROR_IN_FORM;
  972.         List.Next=NULL;
  973.         return List;
  974.     }
  975.  
  976.     pos+=Read(in,&List.Name,4);
  977.  
  978.     b_read=Read(in,&Head,8);
  979.     ThisNode=&List;
  980.     do
  981.     {
  982.     pos+=b_read;
  983.     for (i=1; i<n; i++)
  984.         if (Head.ckID == Names[i])
  985.         {
  986.             if((ThisNode->Next=(void *)malloc(16))==NULL)
  987.             {
  988.                 List.Size=NO_MEMORY;
  989.                 return List;
  990.             }
  991.  
  992.             ThisNode=ThisNode->Next;
  993.             ThisNode->Next = NULL;
  994.             ThisNode->Name = Head.ckID;
  995.             ThisNode->Size = Head.ckSize;
  996.             ThisNode->Pos  = pos;
  997.         }
  998.     Seek(in,Head.ckSize+(Head.ckSize & 1),OFFSET_CURRENT);
  999.     pos+=Head.ckSize+(Head.ckSize & 1);
  1000.     b_read=Read(in,&Head,8);
  1001.     }
  1002.     while ((ThisNode->Name!=ID_BODY) && (b_read==8));
  1003.  
  1004.     List.Size=GOOD_FILE;
  1005.     return List;
  1006. }
  1007.